package com.dobbinsoft.iotechn.device.mqtt;

import com.dobbinsoft.iotechn.device.constant.DeviceConst;
import com.dobbinsoft.iotechn.device.mqtt.handler.IotMqttMessageHandler;
import com.dobbinsoft.iotechn.device.mqtt.serializer.IotMqttDeserializer;
import com.dobbinsoft.iotechn.device.mqtt.serializer.IotMqttSerializer;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.Map;

/**
 * Description:
 * User: rize
 * Date: 2020/6/22
 * Time: 14:08
 */
public class IotMqttClient {

    // 设备向服务器发消息的TOPIC
    private static final String TOPIC = "$share/server/" + DeviceConst.TOPIC_UP + "+";

    @Value("${com.dobbinsoft.iotechn.mqtt.username}")
    private String username;

    @Value("${com.dobbinsoft.iotechn.mqtt.password}")
    private String password;

    @Value("${com.dobbinsoft.iotechn.mqtt.broker}")
    private String broker;

    @Autowired
    private Map<Integer, IotMqttMessageHandler> messageHandleRouter;

    @Autowired
    private IotMqttDeserializer iotMqttDeserializer;

    @Autowired
    private IotMqttSerializer iotMqttSerializer;

    @Autowired
    private IotMqttManagerClient iotMqttManagerClient;

    private MqttClient mqttClient;

    private static final Logger logger = LoggerFactory.getLogger(IotMqttClient.class);

    public void connect() throws Exception {
        this.mqttClient = new MqttClient(broker, username);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        connOpts.setCleanSession(true);
        connOpts.setUserName(username);
        connOpts.setPassword(password.toCharArray());
        // IotMqttCallback 可视为 IotMqttClient 的一部分，本可以将此类实现接口，单为了方便看代码，所以将其重新定义一个类
        mqttClient.setCallback(new IotMqttCallback(mqttClient, messageHandleRouter, iotMqttDeserializer, TOPIC, iotMqttManagerClient));
        mqttClient.connect(connOpts);
        mqttClient.subscribe(TOPIC);
    }

    public boolean send(String accessKeyId, Object obj) {
        return send(DeviceConst.TOPIC_DOWN, accessKeyId, obj);
    }

    public boolean send(String prefix, String accessKeyId, Object obj) {
        try {
            MqttMessage message = new MqttMessage();
            message.setPayload(iotMqttSerializer.toBytes(obj));
            message.setQos(1);
            message.setRetained(false);
            this.mqttClient.publish(prefix + accessKeyId, message);
            return true;
        } catch (Exception e) {
            logger.error("[MQTT 应用服务器] 发送异常; accessKeyId=" + accessKeyId + ";payload=" + new String(iotMqttSerializer.toBytes(obj)), e);
            return false;
        }
    }

}
